#include "ogreapplication.h"

#include <CEGUI/CEGUISchemeManager.h>

using namespace Ogre;
using namespace std;

namespace
{
  void
  parseResourceLocationFrom(const String& resourcesFileName)
  {
    // Load resource paths from config file
    ConfigFile cf;
    cf.load(resourcesFileName);
    // Go through all sections & settings in the file
    ConfigFile::SectionIterator seci = cf.getSectionIterator();
    while (seci.hasMoreElements())
    {
      String secName = seci.peekNextKey();
      ConfigFile::SettingsMultiMap* settings = seci.getNext();
      for (ConfigFile::SettingsMultiMap::iterator i = settings->begin();
					 i != settings->end(); ++i)
      {
				String typeName = i->first;
				String archName = i->second;
				ResourceGroupManager::getSingleton().addResourceLocation(
					archName, typeName, secName);
      }
    }
  }
}
//************************************************************
// Implementation of OgreApplication
//************************************************************
OgreApplication::OgreApplication(Ogre::String name)
  : mName(name)
	, mRoot(NULL)
	, mWindow(NULL)
	, mEventProcessor(NULL)
	, mGUIRenderer(NULL)
	, mGUISystem(NULL)
	, move(Vector3(0,0,0))
    , moveRootNode(0)
	, mQuitRequested(false)

{
}
OgreApplication::~OgreApplication()
{
  if (mEventProcessor) delete mEventProcessor;
  if (mTrackball)      delete mTrackball;
  if (mGUISystem)      delete mGUISystem;
  if (mGUIRenderer)    delete mGUIRenderer;
  if (mRoot)           delete mRoot;
}
void
OgreApplication::addResourceLocationFrom(const String& fileName)
{
  mResourcesFileNames.push_back(fileName);
}
void
OgreApplication::create(const String& pluginsFileName,const String& configFileName,const String& logFileName,SceneType sceneType)
{
  //////////////////////////////////////////////////////////////
  // Initialization of Root and RenderWindow
  //////////////////////////////////////////////////////////////
  mRoot = new Root(pluginsFileName,configFileName,logFileName);
  if (!mRoot->restoreConfig())
  {
    if (!mRoot->showConfigDialog())
    {
      throw Exception(0,"user quitted config dialog","OgreApplication::init()",__FILE__,__LINE__);
    }
  }
  mWindow = mRoot->initialise(true,mName);
  //////////////////////////////////////////////////////////////
  // Initializing resources
  //////////////////////////////////////////////////////////////
  for_each(mResourcesFileNames.begin(),mResourcesFileNames.end(),parseResourceLocationFrom);
  ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
  //////////////////////////////////////////////////////////////
  // Initialization of Scene
  //////////////////////////////////////////////////////////////
  mSceneManager = mRoot->createSceneManager(sceneType,"sceneManager");
  mCamera = mSceneManager->createCamera("Camera");
  mCamera->setPosition(Vector3(0.0f,0.0f,500.0f));
  mCamera->lookAt(Vector3(0.0f,0.0f,0.0f));
  mCamera->setNearClipDistance(5.0f);
  mCamera->setFarClipDistance(5000.0f);
  ////////////////////////////////////////////////////////////
  // Binding of Scene and RenderWindow
  ////////////////////////////////////////////////////////////
  mViewport = mWindow->addViewport(mCamera);
  mViewport->setBackgroundColour(ColourValue(0.0f,0.0f,0.0f));
  mCamera->setAspectRatio(Real(mViewport->getActualWidth()) /
													Real(mViewport->getActualHeight()));
  ////////////////////////////////////////////////////////////
  // Initialize GUI
  ////////////////////////////////////////////////////////////
  mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow,Ogre::RENDER_QUEUE_OVERLAY,
																							false,3000,
																							mSceneManager);
  mGUISystem = new CEGUI::System(mGUIRenderer);

  CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme");
  mGUISystem->setDefaultMouseCursor(reinterpret_cast<const CEGUI::utf8*>("TaharezLook"),
																		reinterpret_cast<const CEGUI::utf8*>("MouseArrow"));
  CEGUI::MouseCursor::getSingleton().setImage(CEGUI::System::getSingleton().getDefaultMouseCursor());
  ////////////////////////////////////////////////////////////
  // Managing input
  ////////////////////////////////////////////////////////////
  mRoot->addFrameListener(this);

  mTrackball = new Trackball(mGUIRenderer,mGUISystem,mCamera,mSceneManager);

  mEventProcessor = new EventProcessor();
  mEventProcessor->addKeyListener(this);
  mEventProcessor->addMouseListener(mTrackball);
  mEventProcessor->addMouseMotionListener(mTrackball);
  //////////////////////////////////////////////////////////////
  //  User initialization (subclassed)
  //////////////////////////////////////////////////////////////
  init();
}
void
OgreApplication::run()
{
  mEventProcessor->initialise(mWindow);
  mEventProcessor->startProcessingEvents();
  mRoot->startRendering();
}
void
OgreApplication::keyClicked(KeyEvent *e)
{
}
void
OgreApplication::keyPressed(KeyEvent *e)
{
}
void
OgreApplication::keyReleased(KeyEvent *e)
{
}
bool
OgreApplication::frameStarted(const FrameEvent& evt)
{
  return true;
}

bool
OgreApplication::frameEnded(const FrameEvent& evt)
{  return !mQuitRequested;
}
void
OgreApplication::init()
{
}
void
OgreApplication::requestQuit()
{
  mQuitRequested = true;
}
